#ifndef TINX_FS_MINIX_H
#define TINX_FS_MINIX_H

#include <tinx/buffer.h>
#include <tinx/fs.h>
#include <tinx/stat.h>
#include <tinx/bitmap.h>

#define MINIX_NAME_LEN 14
#define MINIX_MAGIC 0x137f

#define BLOCK_SIZE 1024

#define BLOCK_BITS (BLOCK_SIZE * 8)
#define BLOCK_DENTRYS (BLOCK_SIZE / sizeof(minix_dentry_t))
#define BLOCK_INODES (BLOCK_SIZE / sizeof(minix_inode_t))
#define BLOCK_INDEXES (BLOCK_SIZE / sizeof(u16))         // 块索引数量
#define DIRECT_BLOCK (7)                                               // 直接块数量
#define INDIRECT1_BLOCK BLOCK_INDEXES                                  // 一级间接块数量
#define INDIRECT2_BLOCK (INDIRECT1_BLOCK * INDIRECT1_BLOCK)            // 二级间接块数量
#define TOTAL_BLOCK (DIRECT_BLOCK + INDIRECT1_BLOCK + INDIRECT2_BLOCK) // 全部块数量

#define MINIX_IMAP_NR 8
#define MINIX_ZMAP_NR 8

typedef struct minix_data_t
{
    struct buffer_t *imaps[MINIX_IMAP_NR];
    struct buffer_t *zmaps[MINIX_ZMAP_NR];
} minix_data_t;

typedef struct minix_desc_t
{
    u16 inodes; // inode 数量
    u16 zones; // 块数量
    u16 imap_blocks;
    u16 zmap_blocks;
    u16 data;
    u16 log_zone_size;
    u32 max_size;
    u16 magic;
} minix_desc_t;

typedef struct minix_inode_t
{
    u16 mode;
    u16 uid;
    u32 size;
    u32 mtime;
    u8 gid;
    u8 nlinks;
    u16 zone[9];
} minix_inode_t;

typedef struct minix_dentry_t
{
    u16 nr;
    char name[MINIX_NAME_LEN];
} minix_dentry_t;

idx_t minix_ialloc(super_t *super);
void minix_ifree(super_t *super, idx_t nr);

idx_t minix_balloc(super_t *super);
void minix_bfree(super_t *super, idx_t nr);
idx_t minix_bmap(inode_t *inode, idx_t block, bool creat);

inode_t *minix_iget(super_t *super, idx_t nr);
inode_t *minix_new_inode(super_t *super, idx_t nr);

int minix_read_super(int dev, super_t *super);
int minix_put_super(super_t *super);
int minix_mkfs(int dev, int icount);

int minix_truncate(inode_t *inode);
int minix_read(inode_t *inode, void *addr, int count, int offset);
int minix_write(inode_t *inode, void *addr, int count, int offset);
int minix_readdir(file_t *file, dentry_t *entry, int count);

int minix_open(inode_t *dir, char *name, int flags, int mode, inode_t **result);
int minix_close(inode_t *inode);
int minix_stat(inode_t *inode, stat_t *statbuf);

buffer_t *minix_add_entry(inode_t *dir, char *name, minix_dentry_t **entry);
buffer_t *minix_find_entry(inode_t **dir, char *name, char **next, minix_dentry_t **entry);

int minix_rmdir(inode_t *dir, char *name);
int minix_mkdir(inode_t *dir, char *name, int mode);

int minix_link(inode_t *odir, char *oldname, inode_t *ndir, char *newname);
int minix_unlink(inode_t *dir, char *name);

int minix_permission(inode_t *inode, int mask);
int minix_namei(inode_t *dir, char *name, char **next, inode_t **result);
int minix_mknod(inode_t *dir, char *name, int mode, int dev);

char *minix_strncpy(char *dest, char *src, size_t count);
int minix_match(char *name, char *entry_name, char **next);

#endif